package uriel.frankel.model;


public class Algorithem {
	private static final int HYBRID_REFUND = 550;
	//private static final int VALUE_OF_1_POINT_2012 = 215;
	
	private static final double PERCENT = 0.01;
	
	//private static final int PENSION_TOP_SALARY_2012 = 47600;
	//private static final int PENSION_TOP_SALARY_2013 = 35312;
	private volatile static Algorithem instance;

	boolean mIsTrainingFund = true;
	
	public void enableTrainingFund(boolean isEnable){
		mIsTrainingFund = isEnable;
	}
	public double points = 2.25;
	private double mSalaryWithoutPension;
	public void setSalaryWithoutPension(double SalaryWithoutPension) {
		mSalaryWithoutPension = SalaryWithoutPension;
	}
	private double baseSalary;
	private double socialPaymentSalary;
	private double mTaxesSalary;
	
	private double SocialPayment;
	double InTheBank;
	public double driving;
	public boolean aboveCeilinOfKerenHishtalmut = false;
	public double kerenPercantage;
	private double incomeTax;
	private final double healthTaxAndSocialSecurityStep = 5297;
	private final double healthTaxAndSocialSecurityTopTaxIncome = 42435;
	private double healthTax;
	private double socialSecurity;
	private boolean leasing;
	private double carPrice;
	private boolean hybrid = false;
	private final double CAR_PRICE_ROOF = 490020;
	private double monthlyPaymentForCar = 0.0;
	private Pension pension;
	private AdvancedStudyFund hishtalmut;
	private final double HEALTH_TAX_FIRST_STAGE_PERCENT  = 3.1*PERCENT;
	private final double HEALTH_TAX_SECOND_STAGE_PERCENT = 5*PERCENT;

	public double GetIncomeTax() {
		return incomeTax;
	}

	public double getsocialSecurity() {
		return socialSecurity;
	}

	public double GetHealthTax() {
		return healthTax;
	}

	public double GetPenstionPayment() {
		return pension.removeFromBankSalary();
	}

	public double GetTrainingFund() {
		return hishtalmut.removeFromBankSalary();
	}

	private Algorithem() {
		kerenPercantage = 0.025;
		
		driving = 0;
		mSalaryWithoutPension = 0;
		
		
	}

	// singleton
	public static Algorithem GetInstance() {
		if (instance == null) {
			synchronized (Algorithem.class) {
				if (instance == null) {
					instance = new Algorithem();
				}
			}
		}
		return instance;

	}


	public double Calculate() {
		
		// דבר ר�?שו�? יש �?נו שכר יסוד
		// �?�?נו נחסר תש�?ו�? �?חברה ש�?נו עבור �?יסינג
		if (isLeasing()) {
			socialPaymentSalary = baseSalary - monthlyPaymentForCar;
		} else {
			socialPaymentSalary = baseSalary;
		}

		mTaxesSalary = baseSalary +  mSalaryWithoutPension + mBenefits;
		if (isLeasing()) {
			mTaxesSalary -=  monthlyPaymentForCar;
		}else{
			// נוסיף �?ברוטו נסיעות ב�?ידה ו�?נחנו �?�? �?וקחי�? �?יסינג
			mSalaryWithoutPension +=driving;
			mTaxesSalary += driving;
		}
		//והנה הח�?ק �?ה�?שכורת שהו�? �?�? �?סוצי�?�?י (כ�?ו שעות נוספות ג�?וב�?�?יות 
		
		
		
		//setSumedIrs(int index)שכר �?�?ס הכנסה
		//פה נכנס ה�?ס ע�? ה�?יסינג וג�? עוד קר�? השת�?�?ות �?ע�? התקרה
		// TODO: קר�? השת�?�?ות �?ע�? התקרה
		if(isLeasing()){
			mTaxesSalary = mTaxesSalary + calculateLeasingPayment();
		}
		
		//this is how much the worker pay from his salary
		//צרי�? �?הוסיף �?ת הקונספט ש�? קר�? השת�?�?ות �?ע�? התקרה
		if(mIsTrainingFund){
			hishtalmut = new AdvancedStudyFund(socialPaymentSalary);
			mTaxesSalary += hishtalmut.addThisMoneyToTaxesSalary();
		}else{
			hishtalmut = new AdvancedStudyFund(0);
		}
		
		pension = new Pension(socialPaymentSalary,mPensionPercent);
		mTaxesSalary += pension.addThisMoneyToTaxesSalary();
		
		//חישוב מס הכנסה
		IncomeTax inTax = new IncomeTax(mTaxesSalary, points, pension.removeFromBankSalary());
		incomeTax = inTax.getIncomeTax();
		
		 

		calculateHealthTax();
		calculateSocialSecurity();
		SocialPayment = GetSocialPayment();
		InTheBank =0;
		InTheBank += baseSalary;
		InTheBank += mSalaryWithoutPension;
		InTheBank -= incomeTax;
		InTheBank -= SocialPayment ;
		InTheBank-=pension.removeFromBankSalary();
		InTheBank-=hishtalmut.removeFromBankSalary();
		
		if (isLeasing()) {
			InTheBank -=  monthlyPaymentForCar;
		}
		
		return InTheBank; 
	}

	


	private double calculateLeasingPayment() {
		if (carPrice > CAR_PRICE_ROOF) {
			carPrice = CAR_PRICE_ROOF;
		} else if (carPrice < 0) {
			return 0;
		}

		double payment = carPrice * 0.0248;
		if (isHybrid()) {
			payment -= HYBRID_REFUND;
		}
		return payment;
	}

	public double GetInTheBank() {
		return InTheBank;
	}

	

	public double GetSocialAlocation() {
		return (hishtalmut.removeFromBankSalary() + pension.removeFromBankSalary());
	}

	public double GetTaxes() {
		return incomeTax + SocialPayment;
	}

	private double GetSocialPayment() {
		return healthTax + socialSecurity;
	}

	private void calculateHealthTax() {
		if (mTaxesSalary < healthTaxAndSocialSecurityStep)
			healthTax = mTaxesSalary * HEALTH_TAX_FIRST_STAGE_PERCENT;
		else if (mTaxesSalary < healthTaxAndSocialSecurityTopTaxIncome)
			healthTax = healthTaxAndSocialSecurityStep * HEALTH_TAX_FIRST_STAGE_PERCENT
					+ (mTaxesSalary - healthTaxAndSocialSecurityStep) * HEALTH_TAX_SECOND_STAGE_PERCENT ;
		else
			healthTax = (healthTaxAndSocialSecurityStep * HEALTH_TAX_FIRST_STAGE_PERCENT)
					+ (healthTaxAndSocialSecurityTopTaxIncome - healthTaxAndSocialSecurityStep)
					* HEALTH_TAX_SECOND_STAGE_PERCENT;
	}

	
		
	
	private void calculateSocialSecurity() {
		// חישוב �?ס ביטוח �?�?ו�?י
		// יsetSumedIrs(int index)ש �?דרגות בהפרשות �?ביטוח �?�?ו�?י
		// עד ה�?דרגה הר�?שונה �?ופרת 0.4 �?חוז
		if (mTaxesSalary < healthTaxAndSocialSecurityStep){
			socialSecurity = mTaxesSalary * 0.004;
		//  (40790�?�?שכורת שנ�?וכה �?התקרה (נכו�? �?2012 �?דובר ב
		//   יופרשו רק 7 �?חוז �?ה�?שכורת �?הח�?ק ש�?ע�?
			// �?ה�?דרגה הר�?שונה 
		}else if (mTaxesSalary < healthTaxAndSocialSecurityTopTaxIncome){
			socialSecurity = healthTaxAndSocialSecurityStep * 0.004
					+ (mTaxesSalary - healthTaxAndSocialSecurityStep) * 0.07;
		}else{
			// טוב יש גבו�? �?עד כ�?ה �?פשר �?ח�?וב �?כ�? �?�? �?תה �?רוויח הרבה �?ז �?רח�?י�? ע�?י�?
			socialSecurity = (healthTaxAndSocialSecurityStep * 0.004)
					+ (healthTaxAndSocialSecurityTopTaxIncome - healthTaxAndSocialSecurityStep)
					* 0.07;
		}
	}


	
	private double mPensionPercent = 5*PERCENT;
	
	
	
	



	
	public boolean isLeasing() {
		return leasing;
	}

	public void setLeasing(boolean leasing) {
		this.leasing = leasing;
	}

	public boolean isHybrid() {
		return hybrid;
	}

	public void setHybrid(boolean hybrid) {
		this.hybrid = hybrid;
	}

	public double getCarPrice() {
		return carPrice;
	}

	public void setCarPrice(double carPrice) {
		if(carPrice<0){
			throw new IllegalArgumentException("car's price cannot be under zero (not in Israel for sure)");
		}
		this.carPrice = carPrice;
	}

	public void setMonthlyPaymentForCar(double monthlyPaymentForCar) {
		if(monthlyPaymentForCar<0){
			throw new IllegalArgumentException("car's price cannot be under zero (not in Israel for sure)");
		}
		this.monthlyPaymentForCar = monthlyPaymentForCar;
	}

	public double getMonthlyPaymentForCar() {
		return monthlyPaymentForCar;
	}

	public void setBaseSalary(double baseSalary) {
		this.baseSalary = baseSalary;
	}

	public void setAboveKeren(boolean isAbove) {
		aboveCeilinOfKerenHishtalmut = isAbove;
	}

	public void setPensionPercentage(double percent) {
		mPensionPercent  = percent;
		
	}

	private double mBenefits = 0;
	public void setBenefits(double benefits) {
		mBenefits = benefits;
	}

	public double getTrainingFundMoneyAfter6Years(){
		return hishtalmut.getMoneyAfter6Years();
	}

}